﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
 
using System.Net; 
using System.Threading;
using System.Windows.Forms; 
using System.IO;
 

namespace screen_socket_server
{
    class Server
    {
        private string localIP;
        private Bitmap screenNow;
        private string[] terminalList;
        private int listenPort;
        private int screenHeight;
        private int screenWidth;
        private bool isWork;
        private byte[] buffer;
        private string errorMessage;
        private Socket server;
 
 
        public Server(int listenPort)
        {
            screenWidth  = Screen.PrimaryScreen.Bounds.Width;
            screenHeight = Screen.PrimaryScreen.Bounds.Height;
            ScreenNow = new Bitmap(screenWidth, screenHeight);
            IsWork = false;
 
            this.listenPort = listenPort;
            //获取本地ip地址
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        //限制了实验室网段或者学校内网
                        if (IpEntry.AddressList[i].ToString().Contains("192.168.199") || IpEntry.AddressList[i].ToString().Contains("114.213"))
                        {
                            LocalIP = IpEntry.AddressList[i].ToString();
                            break;
                        }
                    }
                }
                if (LocalIP == null)
                    LocalIP = "";
            }
            catch (Exception ex)
            {
                errorMessage =  ex.Message;
                showErrorMessage();
            }
        }
        
        public string[] TerminalList { get {return terminalList;} set{terminalList = value; }}
        public string LocalIP { get {return  localIP;} set { localIP = value; }}
        public Bitmap ScreenNow { get { return screenNow;} set { screenNow = value; }}
        public bool IsWork { get { return isWork; } set { isWork = value; } }
 
        public void showErrorMessage()
        {
            
        }
 
        public void startService()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse(LocalIP);
            server.Bind(new IPEndPoint(ip, listenPort));
            server.Listen(10);
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
            Thread catchScreen = new Thread(screenUpdate);
            catchScreen.Start();
            IsWork = true;
        }
 
        private void ListenClientConnect()
        {
            while (true)
            {
                Socket client = server.Accept();  // 这里Accept() 如果没有新的客户socket进来（重点！新的socket），那么就会一直阻塞
                Thread sendThread = new Thread(sendPic);
                sendThread.Start(client);
            }
        }
 
        private void screenUpdate()
        {
            Bitmap temp = new Bitmap(screenWidth, screenHeight);
            Graphics gc = Graphics.FromImage(temp);
            while (true)
            {
                gc.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(screenWidth, screenHeight));
                imgtoBytes(temp);
                screenNow = new Bitmap(temp);
                GC.Collect();
                Thread.Sleep(500);
            }
        }
        
        private void imgtoBytes(Bitmap bitmap)
        {
            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
            buffer = ms.GetBuffer();
            ms.Close();
        }
 
        private void sendPic(object clientSocket)
        {
            Socket client = (Socket)clientSocket;
            byte[] receiveBuffer = new byte[1024];
            byte[] imageCopy;
            while (true)
            {
                try
                {
                    //客户端返回确认后才发送新的数据 (这里怎么判断的？ 如果客户没有确认返回，下面这行的结果是null 会直接跳转到catch ！
                    int receiveLength = client.Receive(receiveBuffer);
                    imageCopy = new byte[buffer.Length];
                    Buffer.BlockCopy(buffer, 0, imageCopy, 0, buffer.Length);
                    byte[] dataLength = BitConverter.GetBytes(imageCopy.Length);
                    client.Send(dataLength);
                    receiveLength = client.Receive(receiveBuffer);
                    client.Send(imageCopy);
                }
                catch
                {
                    //这里要return 不然尝试次数一多,线程就堆积了
                    return;
                    //do Nothing,just break
                }
            }
        } 
    }
}
